<template>
  <div class="json-editor" ref="root"></div>
</template>

<script>
import {defineComponent} from 'vue';
import _ from 'lodash';
import {JSONEditor} from 'vanilla-jsoneditor';

export default defineComponent({
  name: 'ArkJsonEditor',
  emit: ['changeContent'],
  props: {
    // options中的mode传入无用，根据json的类型自动判断
    options: {
      type: Object,
      default() {
        return {};
      },
    },
    content: {
      type: [Object, String],
      default: '',
    }
  },
  data() {
    return {
      editorInstance: {},
      optionsVariable: {
        mode: 'text'
      },
    };
  },
  watch: {
    content: {
      deep: true,
      handler(newVal, oldVal) {
        // 值未发生改变
        let newValObj = newVal;
        if (typeof newVal === 'string') {
          newValObj = JSON.parse(newVal);
        }

        let oldValObj = oldVal;
        if (typeof oldVal === 'string') {
          oldValObj = JSON.parse(oldVal);
        }

        if (_.isEqual(newValObj, oldValObj)) return;

        // 编辑器未初始化
        if (!this.editorInstance) return;

        // 更新
        let content = {};
        if (this.optionsVariable.mode === 'text') {
          try {
            content.text = JSON.stringify(newValObj, null, 2);
          } catch (e) {
            content.text = newValObj;
          }
        } else if (this.optionsVariable.mode === 'tree') {
          content.json = newValObj;
        }
        this.editorInstance.update(content);
      },
    },
  },
  mounted() {
    this.init();
  },
  beforeUnmount() {
    this.editorInstance?.destroy();
  },
  methods: {
    init() {
      // 根据传入options初始化optionsVariable
      const options = _.cloneDeep(this.options);
      const optionsVariable = _.cloneDeep(this.optionsVariable);
      this.optionsVariable = _.defaultsDeep(options, optionsVariable);

      // 根据传入content类型初始化content配置
      let content = {};
      if (typeof this.content === 'string') {
        try {
          content.text = JSON.stringify(JSON.parse(this.content), null, 2);
        } catch (e) {
          content.text = this.content;
        }
      } else if (typeof this.content === 'object') {
        this.optionsVariable.mode = 'tree';
        content.json = this.content;
      }

      // 初始化Editor
      let el = this.$refs.root;
      let thisVue = this;
      this.editorInstance = new JSONEditor({
        target: el,
        props: {
          ...this.optionsVariable,
          content,
          onChangeMode: thisVue.changeMode,
          onChange: thisVue.changeContent,
        },
      });
    },
    changeMode(mode) {
      this.optionsVariable.mode = mode;
    },
    changeContent(updatedContent) {
      let update;
      if (this.optionsVariable.mode === 'text') {
        update = updatedContent.text;
      } else if (this.optionsVariable.mode === 'tree') {
        update = updatedContent.json;
      }

      this.$emit('changeContent', update);
    },

    // 供外部调用，内部未使用
    getEditorInstance() {
      return this.editorInstance;
    },
  },
});
</script>

<style scoped>
.json-editor {
  :deep(.jse-main) {
    @apply max-h-[400px] min-h-[300px];
  }
}
</style>
